#include "stackplatemanager.h"

#include "systemconfiguration.h"
#include "component_log.h"
#include "componentmanager.h"

#include "stackplatecheckdig.h"
#include "stackplatesql.h"

using namespace plate;

StackPlateManager::StackPlateManager(QObject* parent)
	: ComponentBase(parent)
{
	m_name = u8"码垛托盘管理组件";
	m_type = Component::component_stackPlate;
}

StackPlateManager::~StackPlateManager()
{}

QList<StackPlate*> StackPlateManager::GetPlateList()
{
	QList<StackPlate*> plates;
	for (auto& iter : m_plates) {
		plates.append(iter.second);
	}
	return plates;
}

StackPlate* StackPlateManager::GetPlate(const QString& id)
{
	if (m_plates.find(id) != m_plates.end()) {
		return m_plates[id];
	}

	return {};
}


// 组件初始化处理函数
int StackPlateManager::ComponentInit()
{
	auto ids = syscfg->GetStackPlateIds();
	if (ids.isEmpty()) {
		log_trace("Not config stack Plate, so dont neet creat stack plate component");
		return COMMON_ERROR;	// 未配置码垛托盘信息，无需创建码垛托盘管理组件
	}
	if (!plateSql->Init()) {
		SetWarningmsg("数据库初始化失败，托盘数据无法写入数据库");
	}

	for (auto& id : ids) {
		auto cfg = syscfg->GetStackPlateCfg(id);
		plate::PlateInfo param = {};
		param.id = cfg.id;
		param.di = cfg.di;
		param.alg = cfg.alg;
		param.base = cfg.base;
		param.rang = cfg.maxsize;
		param.dirOdd = cfg.dirOdd;
		param.dirEven = cfg.dirEven;
		auto temp = new StackPlate();
		if (temp->Init(param)) {
			log_trace("stack plate {} Init successed");
			m_plates.emplace(cfg.id, temp);
		} else {
			SetErrmsg(QString("%1初始化失败").arg(cfg.id));
			return SERIOUS_ERROR;
		}
	}

	// 订阅wcsmsg组件的任务消息
	auto wcs = m_ob->GetComponent(Component::component_wcsrec);
	if (wcs == nullptr) {
		SetErrmsg("获取wcs消息组件未加载", false);
		return SERIOUS_ERROR;
	}
	bool ret = wcs->RegisterSubscriberFunction((int)WCSMsgType::wcs_msg_plate_arrive, [&](const QByteArray& info) {
		return this->OnPlateArrive(info);
		});
	if (!ret) {
		SetErrmsg("订阅wcs到位消息失败", false);
		return SERIOUS_ERROR;
	}

	ret = wcs->RegisterSubscriberFunction((int)WCSMsgType::wcs_msg_plate_move, [&](const QByteArray& info) {
		return this->OnPlateMove(info);
		});
	if (!ret) {
		SetErrmsg("订阅wcs移走消息失败", false);
		return SERIOUS_ERROR;
	}

	m_dlg = new StackPlateCheckDIg();
	QList<StackPlate*> plates;
	for (auto& iter : m_plates) {
		plates.append(iter.second);
	}

	if (!m_dlg->Init(plates)) {
		SetErrmsg("码垛托盘校验窗口初始化失败", false);
		return SERIOUS_ERROR;
	}


	log_trace("Stack plate componetn load success, plate num = {}", m_plates.size());
	return 0;
}
/*自检接口*/
bool StackPlateManager::ComponentCheckSelfState()
{
	// 人工检查窗口
	if (m_dlg->StartReset()) {
		log_trace("manual check stack plate OK");
		return true;
	}
	SetErrmsg("码垛托盘人工校验窗口未正常校验", false);

	for (auto& iter : m_plates) {
		iter.second->SetPlateRelease();
	}
	return true;
}
/*复位接口*/
bool StackPlateManager::ComponentSelfReset()
{

	return true;
}

void* StackPlateManager::GetPoint(const QString& id)
{
	return GetPlate(id);
}

bool StackPlateManager::ExcuteCmd(int cmd, const QByteArray& input, QByteArray& output)
{
	StackPlateCmd type = (StackPlateCmd)cmd;
	switch (type) {
	case plate::StackPlateCmd::stackplate_get_plateState:
		break;
	default:
		break;
	}
	output = "错误的命令类型";
	return false;
}

int StackPlateManager::OnPlateArrive(const QByteArray& data)
{
	PlateArriveInfo info = {};
	info.fromJson(data);

	if (m_plates.find(info.placeNo()) != m_plates.end()) {
		auto& plate = m_plates[info.placeNo()];
		plate->SetPlateArrived();
		log_trace("plate {} is arrived, plateNO = {}", info.placeNo(), info.plateId());
		return 0;
	}
	log_error("Not find stack plate name is {}", info.placeNo());
	return -1;
}

int StackPlateManager::OnPlateMove(const QByteArray& data)
{
	PlateMoveInfo info = {};
	info.fromJson(data);

	if (m_plates.find(info.placeNo()) != m_plates.end()) {
		auto& plate = m_plates[info.placeNo()];
		if (!plate->SetPlateMoved()) {
			SetWarningmsg("设置托盘为移走状态失败");
		}
		log_trace("plate {} is moved", info.placeNo());
		return 0;
	}

	log_error("Not find plate id {}", info.placeNo());
	return -1;
}
